package com.dd.stack.se.stream.concurrent.reentrantlock;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Author liuxianmeng
 * @CreateTime 2025/9/28 15:18
 * @Description 类功能作用说明
 */
public class ConditionExample {
    private final ReentrantLock lock = new ReentrantLock();
    private final Condition notEmpty = lock.newCondition(); // 非空条件（消费者等待）
    private final Condition notFull = lock.newCondition();  // 非满条件（生产者等待）
    private final Queue<Integer> queue = new LinkedList<>();
    private static final int CAPACITY = 5; // 队列最大容量

    // 生产者：添加元素，队列满则等待
    public void produce(int num) throws InterruptedException {
        lock.lock();
        try {
            while (queue.size() == CAPACITY) {
                System.out.println("队列满，生产者等待...");
                notFull.await(); // 等待非满条件
            }
            queue.add(num);
            System.out.println("生产：" + num + "，队列大小：" + queue.size());
            notEmpty.signal(); // 唤醒等待非空条件的消费者
        } finally {
            lock.unlock();
        }
    }

    // 消费者：取出元素，队列空则等待
    public int consume() throws InterruptedException {
        lock.lock();
        try {
            while (queue.isEmpty()) {
                System.out.println("队列空，消费者等待...");
                notEmpty.await(); // 等待非空条件
            }
            int num = queue.poll();
            System.out.println("消费：" + num + "，队列大小：" + queue.size());
            notFull.signal(); // 唤醒等待非满条件的生产者
            return num;
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        ConditionExample example = new ConditionExample();
        // 启动生产者线程
        new Thread(() -> {
            try {
                for (int i = 0; i < 10; i++) {
                    example.produce(i);
                    Thread.sleep(100);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "生产者").start();

        // 启动消费者线程
        new Thread(() -> {
            try {
                for (int i = 0; i < 10; i++) {
                    example.consume();
                    Thread.sleep(300);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "消费者").start();
    }
}
